#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<errno.h>
#include<fcntl.h>
#include<ctype.h>
#include<sys/stat.h>

#define MAXSIZE 1000
#define NONE_REDIR 0
#define INPUT_REDIR 1
#define OUTPUT_REDIR 2
#define APPEND_REDIR 3
#define trim_space(start) while(isspace(*start)) start++




char line[MAXSIZE];
char* args[100] = {NULL};

int lastcode = 0;
int lastsig = 0;
int redir_type = NONE_REDIR;
char *redir_file = NULL;

void commend_check(char *line){
     char* start = line;
     char* end = line + strlen(line);

     while(start < end){
          
	  if (*start == '>'){
	     *start = '\0';
	     start++;
             
	     if (*start == '>'){
	     //	*start = '\0'; 这里不用加，一个'\0'就能隔绝了
		start++;
		redir_type = APPEND_REDIR;
	     }else{
                redir_type = OUTPUT_REDIR;
	     } 
             
	     trim_space(start);
             redir_file = start;
	     break;
         }
	 else if (*start == '<'){
	        *start = '\0';
		redir_type = INPUT_REDIR;

	        start++;
	        trim_space(start);
                redir_file = start;
		break;
	 }
	 else start++;
     }
}


int main(){

  while (1){  
  printf("\n[myshell@vm-centos]$ ");
  fflush(stdout);
  
  redir_type = NONE_REDIR;
  char* s = fgets(line, sizeof(line)-1, stdin);
  assert(s != NULL);
  
  line[strlen(line)-1] = 0;

  commend_check(line);
  args[0] = strtok(line," ");
  

  int i = 1;
  
  if(args[0] != NULL && strcmp(args[0], "ls") == 0)
    args[i++] = (char*)"--color=auto";


  while(args[i++] = strtok(NULL," "))
         ; 
  
  if (args[0] != NULL && strcmp(args[0], "cd") == 0){
     if(args[1] != NULL) chdir(args[1]);
     else chdir(getenv("HOME"));
     continue;
  }

  if (args[0] != NULL && strcmp(args[0], "echo") == 0){
     if (args[1] != NULL && strcmp(args[1],"$?") == 0) 
	     printf("%d %d\n", lastcode, lastsig);
     else    printf("%s\n",args[1]);
     continue;
  }


  pid_t id = fork();
  if (id == 0){

    switch(redir_type){
	case NONE_REDIR: break;
        case INPUT_REDIR: {
	    int fd = open(redir_file, O_RDONLY);
	    if (fd < 0) {perror("open"); exit(errno);}
            dup2(fd,0);
        } break;

	case OUTPUT_REDIR:
	case APPEND_REDIR: {
	    umask(0);
	    int file_status = O_WRONLY | O_CREAT;
	    if (redir_type == APPEND_REDIR) file_status |= O_APPEND;
	    else file_status |= O_TRUNC;
	    int fd = open(redir_file, file_status, 0666);
	    if (fd < 0) {perror("open"); exit(errno);}
	    dup2(fd, 1);
	} break;
        
        default: printf("error\n"); break;			   
    }

    execvp(args[0], args);
    exit(0);
  }
      int status;
      pid_t tmp = waitpid(-1, &status, 0); 

      lastcode = ((status>>8) & 0xFF);
      lastsig = (status & 0x7F);

  }
}
